package cn.danger.com.presenter;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import java.util.List;
import java.util.Map;

import cn.bmob.v3.BmobObject;
import cn.danger.com.app.MyApplication;
import cn.danger.com.db.OperateDaoImpl;
import cn.danger.com.db.ScheduleDaoImpl;
import cn.danger.com.model.action.ScheduleModel;
import cn.danger.com.model.action.ScheduleModelImpl;
import cn.danger.com.model.entity.Operate;
import cn.danger.com.model.entity.Schedule;
import cn.danger.com.model.listener.OnCommonListener;
import cn.danger.com.receiver.AlarmReceiver;
import cn.danger.com.util.Constants;
import cn.danger.com.util.DateUtil;
import cn.danger.com.util.FileCacheService;
import cn.danger.com.util.MyNetManager;
import cn.danger.com.util.SortUtil;
import cn.danger.com.view.CommonView;

/**
 * Created by 俊 on 2017/1/4.
 */
public class SchedulePresenterImpl implements SchedulePresenter {

    private Context context;
    private CommonView view;
    private ScheduleModel model;

    public SchedulePresenterImpl(Context context, CommonView view) {
        this.context = context;
        this.view = view;
        model = new ScheduleModelImpl(context);
    }

    @Override
    public void sendAlarm(Schedule schedule) {
        long time = Long.parseLong(schedule.getDate_start()) - DateUtil.getRemindTime(schedule.getRemind_time());
        Intent intent = new Intent(context, AlarmReceiver.class);
        intent.setAction("remind");
        intent.setData(Uri.EMPTY);
        Log.i("danger", "alarm id:" + schedule.getId());
        intent.putExtra("schedule", schedule);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, schedule.getId(), intent, 0);
        AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        manager.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);
    }

    @Override
    public void cancelAlarm(Schedule schedule) {
        Intent intent = new Intent(context, AlarmReceiver.class);
        intent.setAction("remind");
        intent.setData(Uri.EMPTY);
        intent.putExtra("schedule", schedule);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, schedule.getId(), intent, 0);
        AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        manager.cancel(pendingIntent);
    }

    @Override
    public void addSchedule(final Schedule schedule) {
        if (MyApplication.getOperateCode() == Constants.NETWORK) {
            view.showDialog();
            model.addScheduleToNetwork(schedule, new OnCommonListener() {
                @Override
                public void onSuccess(String objectId) {
                    Schedule new_schedule = new Schedule();
                    new_schedule.setId(schedule.getId());
                    new_schedule.setObjectId(objectId);
                    new_schedule.setUsername(schedule.getUsername());
                    new_schedule.setContent(schedule.getContent());
                    new_schedule.setDate_start(schedule.getDate_start());
                    new_schedule.setType(schedule.getType());
                    new_schedule.setRemind(schedule.getRemind());
                    new_schedule.setRemind_time(schedule.getRemind_time());
                    new_schedule.setRemind_ring(schedule.getRemind_ring());
                    new ScheduleDaoImpl(context).insert(new_schedule);
                    if (new_schedule.getRemind() == 1) {
                        sendAlarm(new_schedule);
                    }
                    view.hideDialog();
                    view.showMessage(Constants.SUCCESS_TO_ADD_SCHEDULE);
                }

                @Override
                public void onError(String error) {
                    view.hideDialog();
                    view.showMessage(error);
                }
            });
        } else if (MyApplication.getOperateCode() == Constants.LOCAL || MyApplication.getOperateCode() == Constants.NOT_LOGIN) {
            if (!TextUtils.isEmpty(schedule.getContent())) {
                try {
                    int id = new ScheduleDaoImpl(context).insert(schedule);
                    Schedule new_schedule = new Schedule();
                    new_schedule.setId(id);
                    new_schedule.setObjectId(schedule.getObjectId());
                    new_schedule.setUsername(schedule.getUsername());
                    new_schedule.setContent(schedule.getContent());
                    new_schedule.setDate_start(schedule.getDate_start());
                    new_schedule.setType(schedule.getType());
                    new_schedule.setRemind(schedule.getRemind());
                    new_schedule.setRemind_time(schedule.getRemind_time());
                    new_schedule.setRemind_ring(schedule.getRemind_ring());
                    if (new_schedule.getRemind() == 1) {
                        sendAlarm(new_schedule);
                    }
                    Operate operate = new Operate();
                    operate.setUsername(schedule.getUsername());
                    operate.setOperate_table("schedule");
                    operate.setOperate_type("add");
                    operate.setOperate_id(id);
                    new OperateDaoImpl(context).insert(operate);
                    view.showMessage(Constants.SUCCESS_TO_SAVE_LOCAL);
                } catch (Exception e) {
                    e.printStackTrace();
                    view.showMessage(Constants.FAIL_TO_SAVE_LOCAL);
                }
            } else {
                view.showMessage(Constants.SCHEDULE_CONTENT_IS_EMPTY);
            }
        }
    }

    @Override
    public void updateSchedule(final Schedule schedule) {
        if (MyApplication.getOperateCode() == Constants.NETWORK) {
            view.showDialog();
            model.updateScheduleToNetWork(schedule, new OnCommonListener() {
                @Override
                public void onSuccess(String objectId) {
                    Schedule origin_schedule = new ScheduleDaoImpl(context).getSchedule(schedule.getId());
                    new ScheduleDaoImpl(context).update(schedule);
                    if (origin_schedule.getRemind() == 1 && schedule.getRemind() == 2) {
                        cancelAlarm(origin_schedule);
                    } else if (origin_schedule.getRemind() == 2 && schedule.getRemind() == 1) {
                        sendAlarm(schedule);
                    } else if (origin_schedule.getRemind() == 1 && schedule.getRemind() == 1) {
                        cancelAlarm(origin_schedule);
                        sendAlarm(schedule);
                    }
                    view.hideDialog();
                    view.showMessage(Constants.SUCCESS_TO_UPDATE_SCHEDULE);
                }

                @Override
                public void onError(String error) {
                    view.hideDialog();
                    view.showMessage(error);
                }
            });
        } else if (MyApplication.getOperateCode() == Constants.LOCAL || MyApplication.getOperateCode() == Constants.NOT_LOGIN) {
            if (!TextUtils.isEmpty(schedule.getContent())) {
                try {
                    new ScheduleDaoImpl(context).update(schedule);
                    Schedule origin_schedule = new ScheduleDaoImpl(context).getSchedule(schedule.getId());
                    new ScheduleDaoImpl(context).update(schedule);
                    if (origin_schedule.getRemind() == 1 && schedule.getRemind() == 2) {
                        cancelAlarm(origin_schedule);
                    } else if (origin_schedule.getRemind() == 2 && schedule.getRemind() == 1) {
                        sendAlarm(schedule);
                    } else if (origin_schedule.getRemind() == 1 && schedule.getRemind() == 1) {
                        cancelAlarm(origin_schedule);
                        sendAlarm(schedule);
                    }
                    Operate operate = new Operate();
                    operate.setUsername(schedule.getUsername());
                    operate.setOperate_table("schedule");
                    operate.setOperate_id(schedule.getId());
                    operate.setOperate_objectId(schedule.getObjectId());
                    operate.setOperate_type("update");
                    new OperateDaoImpl(context).insert(operate);
                    view.showMessage(Constants.SUCCESS_TO_UPDATE_LOCAL);
                } catch (Exception e) {
                    view.showMessage(Constants.FAIL_TO_UPDATE_LOCAL);
                }
            } else {
                view.showMessage(Constants.SCHEDULE_CONTENT_IS_EMPTY);
            }
        }
    }

    @Override
    public void deleteSchedule(final Schedule schedule) {
        if (MyApplication.getOperateCode() == Constants.NETWORK) {
            view.showDialog();
            model.deleteScheduleToNetWork(schedule.getObjectId(), new OnCommonListener() {
                @Override
                public void onSuccess(String message) {
                    new ScheduleDaoImpl(context).delete(schedule.getId());
                    cancelAlarm(schedule);
                    view.hideDialog();
                    view.showMessage(Constants.SUCCESS_TO_DELETE_SCHEDULE);
                }

                @Override
                public void onError(String error) {
                    view.hideDialog();
                    view.showMessage(error);
                }
            });
        } else if (MyApplication.getOperateCode() == Constants.LOCAL || MyApplication.getOperateCode() == Constants.NOT_LOGIN) {
            if (!TextUtils.isEmpty(schedule.getContent())) {
                try {
                    new ScheduleDaoImpl(context).delete(schedule.getId());
                    cancelAlarm(schedule);
                    Operate operate = new Operate();
                    operate.setUsername(schedule.getUsername());
                    operate.setOperate_objectId(schedule.getObjectId());
                    operate.setOperate_id(schedule.getId());
                    operate.setOperate_type("delete");
                    operate.setOperate_table("schedule");
                    new OperateDaoImpl(context).insert(operate);
                    view.showMessage(Constants.SUCCESS_TO_DELETE_LOCAL);
                } catch (Exception e) {
                    view.showMessage(Constants.FAIL_TO_DELETE_LOCAL);
                }
            } else {
                view.showMessage(Constants.SCHEDULE_CONTENT_IS_EMPTY);
            }
        }
    }

    @Override
    public void deleteSchedules(final List<BmobObject> schedules) {
        if (MyApplication.getOperateCode() == Constants.NETWORK) {
            view.showDialog();
            model.deleteSchedulesToNetWork(schedules, new OnCommonListener() {
                @Override
                public void onSuccess(String message) {
                    for (int i = 0; i < schedules.size(); i++) {
                        Schedule schedule = (Schedule) schedules.get(i);
                        new ScheduleDaoImpl(context).delete(schedule.getId());
                        cancelAlarm(schedule);
                    }
                    view.hideDialog();
                    view.showMessage(message);
                }

                @Override
                public void onError(String error) {
                    view.hideDialog();
                    view.showMessage(error);
                }
            });
        } else if (MyApplication.getOperateCode() == Constants.LOCAL || MyApplication.getOperateCode() == Constants.NOT_LOGIN) {
            try {
                for (int i = 0; i < schedules.size(); i++) {
                    Schedule schedule = (Schedule) schedules.get(i);
                    new ScheduleDaoImpl(context).delete(schedule.getId());
                    cancelAlarm(schedule);
                    Operate operate = new Operate();
                    operate.setUsername(schedule.getUsername());
                    operate.setOperate_id(schedule.getId());
                    operate.setOperate_table("schedule");
                    operate.setOperate_objectId(schedule.getObjectId());
                    operate.setOperate_type("delete");
                    new OperateDaoImpl(context).insert(operate);
                }
                view.showMessage(Constants.SUCCESS_TO_DELETE_LOCAL);
            } catch (Exception e) {
                view.showMessage(Constants.FAIL_TO_DELETE_LOCAL);
            }
        }
    }

    @Override
    public List<Integer> getMonthSchedules(String year, String month) {
        FileCacheService service = new FileCacheService(context);
        Map<String, String> map = (Map<String, String>) service.getSharePreference("userInfo");
        List<Integer> default_schedules = new ScheduleDaoImpl(context).getMonthSchedule("default", year, month);
        if (map.get("phone") != null) {
            List<Integer> schedules = new ScheduleDaoImpl(context).getMonthSchedule(map.get("phone"), year, month);
            if (schedules == null) {
                return default_schedules;
            } else {
                if (default_schedules != null) {
                    schedules.addAll(default_schedules);
                }
            }
            return schedules;
        } else {
            if (default_schedules != null) {
                return default_schedules;
            }
        }
        return null;
    }

    @Override
    public List<Schedule> getTodaySchedules() {
        FileCacheService service = new FileCacheService(context);
        Map<String, String> map = (Map<String, String>) service.getSharePreference("userInfo");
        List<Schedule> default_schedules = new ScheduleDaoImpl(context).getTodaySchedule("default");
        if (map.get("phone") != null) {
            List<Schedule> schedules = new ScheduleDaoImpl(context).getTodaySchedule(map.get("phone"));
            if (schedules == null) {
                return SortUtil.sortSchedules(default_schedules);
            } else {
                if (default_schedules != null) {
                    schedules.addAll(default_schedules);
                }
            }
            return SortUtil.sortSchedules(schedules);
        } else {
            if (default_schedules != null) {
                return SortUtil.sortSchedules(default_schedules);
            }
        }
        return null;
    }

    @Override
    public List<Schedule> getDaySchedules(String day) {
        FileCacheService service = new FileCacheService(context);
        Map<String, String> map = (Map<String, String>) service.getSharePreference("userInfo");
        List<Schedule> default_schedules = new ScheduleDaoImpl(context).getDaySchedule("default", day);
        if (map.get("phone") != null) {
            List<Schedule> schedules = new ScheduleDaoImpl(context).getDaySchedule(map.get("phone"), day);
            if (schedules == null) {
                return SortUtil.sortSchedules(default_schedules);
            } else {
                if (default_schedules != null) {
                    schedules.addAll(default_schedules);
                }
            }
            return SortUtil.sortSchedules(schedules);
        } else {
            if (default_schedules != null) {
                return SortUtil.sortSchedules(default_schedules);
            }
        }
        return null;
    }

    @Override
    public void synchronousSchedule() {
        if (new MyNetManager(context).isNetworkAvailable()) {
            if (MyApplication.getOperateCode() != Constants.NOT_LOGIN) {
                synchronous();
            } else {
                view.showMessage(Constants.PLEASE_LOGIN);
            }
        } else {
            view.showMessage(Constants.NETWORK_IS_NOT_AVAILABLE);
        }
    }

    private void synchronous() {
        FileCacheService service = new FileCacheService(context);
        Map<String, String> map = (Map<String, String>) service.getSharePreference("userInfo");
        if (map.get("phone") != null) {
            view.showDialog();
            //获取Operate表内操作的Memo数据
            List<Operate> operates = new OperateDaoImpl(context).queryOperates(map.get("phone"), "schedule");
            List<Operate> default_operates = new OperateDaoImpl(context).queryOperates("default", "schedule");
            List<Schedule> schedules = new ScheduleDaoImpl(context).getSchedules("default");
            if (schedules != null) {
                for (Schedule schedule : schedules) {
                    schedule.setUsername(map.get("phone"));
                    new ScheduleDaoImpl(context).update(schedule);
                }
            }
            if (default_operates != null) {
                for (Operate operate : default_operates) {
                    operate.setUsername(map.get("phone"));
                    new OperateDaoImpl(context).insert(operate);
                    operates.add(operate);
                }
            }
            Log.i("danger", "operate--->>" + operates);
            //遍历在离线时所有对Schedule表的操作
            for (final Operate operate : operates) {
                //如果对Schedule的操作是添加
                if (operate.getOperate_type().equals("add")) {
                    final Schedule schedule = new ScheduleDaoImpl(context).getSchedule(operate.getOperate_id());
                    //向服务器添加Schedule实体
                    model.addScheduleToNetwork(schedule, new OnCommonListener() {
                        @Override
                        public void onSuccess(String objectId) {
                            //删除Operate表内的记录
                            new OperateDaoImpl(context).delete(operate);
                            //将服务器返回的objectId设置给Schedule并保存
                            Schedule new_schedule = new Schedule();
                            new_schedule.setId(schedule.getId());
                            new_schedule.setUsername(schedule.getUsername());
                            new_schedule.setObjectId(objectId);
                            new_schedule.setContent(schedule.getContent());
                            new_schedule.setDate_start(schedule.getDate_start());
                            new_schedule.setType(schedule.getType());
                            new_schedule.setRemind(schedule.getRemind());
                            new_schedule.setRemind_time(schedule.getRemind_time());
                            new_schedule.setRemind_ring(schedule.getRemind_ring());
                            new ScheduleDaoImpl(context).update(new_schedule);
                            Intent intent = new Intent("update_ui");
                            context.sendBroadcast(intent);
                        }

                        @Override
                        public void onError(String error) {
                            view.showMessage(error);
                        }
                    });
                    //如果对Memo的操作是删除
                } else if (operate.getOperate_type().equals("delete")) {
                    //获取Memo实体
                    model.deleteScheduleToNetWork(operate.getOperate_objectId(), new OnCommonListener() {
                        @Override
                        public void onSuccess(String message) {
                            new OperateDaoImpl(context).delete(operate);
                        }

                        @Override
                        public void onError(String error) {
                            view.showMessage(error);
                        }
                    });
                    //如果对Memo的操作是更新
                } else if (operate.getOperate_type().equals("update")) {
                    //获取Memo实体
                    final Schedule schedule = new ScheduleDaoImpl(context).getSchedule(operate.getOperate_id());
                    model.updateScheduleToNetWork(schedule, new OnCommonListener() {
                        @Override
                        public void onSuccess(String message) {
                            new OperateDaoImpl(context).delete(operate);
                        }

                        @Override
                        public void onError(String error) {
                            view.showMessage(error);
                        }
                    });
                }
            }
            view.hideDialog();
            view.showMessage(Constants.SUCCESS_TO_SYNCHRONOUS_SCHEDULE);
        } else {
            view.showMessage(Constants.PLEASE_LOGIN);
        }
    }
}